from commonrules import CommonRules
from Mastergoal.Common.team import Team
from Mastergoal.Common.move import BallMove, PlayerMove

class L2Rules(CommonRules):
    
    @staticmethod
    def correct_player_move(state, move):
        """ Extends basic players moves for level two """
        
        # Check common rules
        if not CommonRules.correct_player_move(state, move):
            return False
        
        # A player can't occupy it's own corner square
        if state.board.own_corner(move.piece.orientation, move.square.col, move.square.row):
            return False
        
        return True
    
    @staticmethod
    def valid_player_move(state, move, cls):
        """ Checks if player move is valid in the current state context """
        
        # Get response from common basic rules
        response = CommonRules.valid_player_move(state, move, L2Rules)
        # assumes tuple
        #if not isinstance(response, tuple):
        #   return response
        
        # If player moves while having the ball and it's not neutral square
        if not response[0] and response[1] != CommonRules.INVALID_MUST_MOVE_BALL:
            return False
        
        neutral_square = L2Rules.neutral_square(state, move)
        
        # if player has the ball and is not neutral square, it can't move
        if not neutral_square and response[1] == CommonRules.INVALID_MUST_MOVE_BALL:
            return response
        
        if CommonRules.ball_around(state, move.square):
            if neutral_square:
                # Player can't leave neutral square position (only move around ball)
                if ( CommonRules.ball_around(state, move.piece.square) 
                     and not CommonRules.ball_around(state, move.square) ):
                    return (False, CommonRules.INVALID_PLAYER_MOVE)
                
                # Player must reach ball when neutral square is in player's area
                if L2Rules.neutral_square_area(state, move, cls):
                    return (False, CommonRules.INVALID_NEUTRAL_IN_AREA)
            
                # If there is neutral square, team with majority get possession of the ball
                if ( not CommonRules.ball_around(state, move.piece.square) 
                     and CommonRules.ball_around(state, move.square) ):
                    return (True, CommonRules.VALID_REACHED_BALL)
                
                # Player can move around the ball during a neutral_square
                if ( CommonRules.ball_around(state, move.piece.square) 
                     and CommonRules.ball_around(state, move.square) ):
                    return (True, CommonRules.VALID_OK)
            return (True, CommonRules.VALID_REACHED_BALL)
        
        return (True, CommonRules.VALID_OK)
    
    @staticmethod
    def valid_ball_move(state, move, cls):
        
        """ Checks if ball move is valid in the current state context """
        
        # Check common basic ball moves
        response = CommonRules.valid_ball_move(state, move)
        if not response[0]:
            return response
        
        if response[1] == CommonRules.VALID_GOAL:
            return response
        
        # response[1] contains majority if True and no goal
        majority = response[1]
       
        # Ball can't be moved if in neutral square 
        if cls.neutral_square(state, move.piece.square):
            return (False, CommonRules.INVALID_BALL_NEUTRAL)
        
        # Check neutral square after moving the ball
        if cls.neutral_square(state, move.square):
            # Player can't leave neutral square
            if CommonRules.around(move.square, move.player_who_moves.square):
                return (False, CommonRules.INVALID_LEAVE_BALL)
            # Player can't leave ball in neutral square in its big area
            if state.board.big_area(move.player_who_moves.orientation, move.square.col, move.square.row):
                return (False, CommonRules.INVALID_LEAVE_BALL)
            
            return (True, CommonRules.VALID_NEUTRAL)
        
        # Check if ball was passed to another player
        elif (not state.board.is_goal(move.player_moving.orientation, move.square.col, move.square.row) 
            and majority == move.player_moving.orientation):
            return (True, CommonRules.VALID_PASS)
        
        return (True, majority)
    
    @staticmethod
    def neutral_square(state, ball_square):
        """ Returns true if there is a neutral square in board """

        teams_around_ball = {Team.UP:0, Team.DOWN:0}
        
        for k,v in state.board.teams.iteritems():
            for player in v.players:
                if CommonRules.around(player.square, ball_square):
                    teams_around_ball[player.orientation] += 1
        
        team_up = teams_around_ball[Team.UP]
        team_down = teams_around_ball[Team.DOWN]
        
        if team_up > 0 and team_down > 0 and team_up == team_down:
            return True
        
        return False
    
    @staticmethod
    def neutral_square_area(state, move, cls):
        """ Checks if there is a neutral square in team area """
        
        ball = state.board.ballpiece
        in_area = False
        if state.board.team_area(move.piece.orientation, ball.square.col, ball.square.row):
           in_area = True
           
        if in_area:   
            if (not CommonRules.ball_around(state, move.square) 
                or CommonRules.around(ball.square, move.piece.square)):
                if in_area:    
                    team = state.board[move.piece.orientation]
                    for player in team.players:
                        if CommonRules.ball_around(state, move.piece.square):
                            continue
                        
                        aux_move = PlayerMove(move.piece, move.square)
                        
                        for i in range(-1,2):
                            for j in range(-1,2):
                                if (i != 0 or j != 0):
                                    aux_move.square.col = ball.square.col + i
                                    aux_move.square.row = ball.square.row + j
                                    #print str(i) + ' ** ' + str(j)
                                    if cls.correct_player_move(state, aux_move):
                                        return True    
                
        return False

